home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 April: Mac OS SDK / Dev.CD Apr 98 SDK1.toast / Development Kits (Disc 1) / QuickDraw 3D / Samples / SampleCode / Plug-in - DistanceProxyGroup / src / dpg.c next >
Encoding:
C/C++ Source or Header  |  1997-08-14  |  26.7 KB  |  1,155 lines  |  [TEXT/MPS ]

  1. /******************************************************************************
  2.  **                                                                             **
  3.  **     Module:        dpg.c                                                      **
  4.  **                                                                          **
  5.  **                                                                          **                                                                     **
  6.  **                                                                          **
  7.  **     Copyright (C) 1996-1996 Apple Computer, Inc.  All rights reserved.     **
  8.  **                                                                          **
  9.  **                                                                          **
  10.  *****************************************************************************/
  11.  
  12. #include "DPGGroup.h"
  13.  
  14. #include "QD3D.h"
  15. #include "QD3DCamera.h"
  16. #include "QD3DMath.h"
  17. #include "QD3DView.h"
  18. #include "QD3DExtension.h"
  19. #include "QD3DGroup.h"
  20.  
  21. #include "dpg.h"
  22. #include "dpgIO.h"
  23. #include "dpgMemory.h"
  24. #include "dpgSortedArray.h"
  25.  
  26. typedef struct TQ3DPGData
  27. {
  28.     TQ3Point3D         refPt;
  29.     unsigned long     flag;
  30. } TQ3DPGData;
  31.  
  32. static unsigned long EgSharedLibrary = NULL;
  33.  
  34. OSErr          DPGInitialize(const CFragInitBlock *initBlock);
  35. TQ3Status     DPGExit(void);
  36.     
  37.  
  38. /******************************************************************************
  39.  **        
  40.  **        Static Prototypes
  41.  **        
  42.  *****************************************************************************/
  43.  
  44. static TQ3XFunctionPointer exDistanceProxyGroup_MetaHandler(
  45.     TQ3XMethodType        methodType);
  46.  
  47. static TQ3Boolean exDistanceProxyGroup_AcceptObject(
  48.     TQ3GroupObject        group,
  49.     TQ3Object            object);
  50.  
  51. static TQ3GroupPosition exDistanceProxyGroup_AddObject(
  52.     TQ3GroupObject        group,
  53.     TQ3Object            object);
  54.     
  55. static TQ3GroupPosition exDistanceProxyGroup_AddObjectBefore(
  56.     TQ3GroupObject        group,
  57.     TQ3GroupPosition    position,
  58.     TQ3Object            object);
  59.     
  60. static TQ3GroupPosition exDistanceProxyGroup_AddObjectAfter(
  61.     TQ3GroupObject        group,
  62.     TQ3GroupPosition    position,
  63.     TQ3Object            object);
  64.  
  65. static TQ3Status exDistanceProxyGroup_SetPositionObject(
  66.     TQ3GroupObject        group,
  67.     TQ3GroupPosition    position,
  68.     TQ3Object            object);
  69.     
  70. static TQ3Object exDistanceProxyGroup_RemovePosition(
  71.     TQ3GroupObject        group,
  72.     TQ3GroupPosition    position);
  73.  
  74.  
  75. static long exiDistanceProxyGroup_CompareDistance(
  76.     float                *key,
  77.     TQ3DistanceData        *data);
  78.     
  79. static TQ3Status exDistanceProxyGroup_AddDistance(
  80.     TQ3GroupObject                            group,
  81.     TQ3DistanceProxyDisplayGroupPrivate        *gPriv,
  82.     TQ3GroupPosition                        position,
  83.     float                                    distance);
  84.  
  85. static TQ3Boolean exDistanceProxyGroup_Find(
  86.     TQ3GroupObject        group,
  87.     TQ3GroupPosition    position);
  88.  
  89. static TQ3Status exDistanceProxyGroup_CalculateDistance(
  90.     TQ3ViewObject                        view,
  91.     TQ3DistanceProxyDisplayGroupPrivate    *gPriv);
  92.  
  93. static TQ3Boolean exDistanceProxyGroup_Visible(
  94.     TQ3DistanceProxyDisplayGroupPrivate    *gPriv,
  95.     TQ3GroupPosition                    position);
  96.  
  97. static TQ3Status exDistanceProxyGroup_ProcessIO(
  98.     TQ3GroupObject                        group,
  99.     TQ3DistanceProxyDisplayGroupPrivate    *gPriv);
  100.  
  101. /******************************************************************************
  102.  **        
  103.  **        Globals
  104.  **        
  105.  *****************************************************************************/
  106.  
  107. TQ3XObjectClass EgDistanceProxyDisplayGroupClass;
  108.  
  109. /******************************************************************************
  110.  **        
  111.  **        DistanceProxy Group Routines
  112.  **        
  113.  *****************************************************************************/
  114.  
  115. static TQ3Status iDPG_New(
  116.     TQ3GroupObject                            group,
  117.     TQ3DistanceProxyDisplayGroupPrivate        *gPriv,
  118.     const TQ3DPGData                        *gData)
  119. {
  120.     group; /* Unused */
  121.         
  122.     gPriv->d            = 0.0;
  123.     gPriv->refPt        = gData->refPt;
  124.     gPriv->flag            = gData->flag;
  125.         
  126.     gPriv->distTblCnt    = 0;
  127.     gPriv->distTbl        = NULL;
  128.  
  129.     gPriv->distIOTbl    = 0;
  130.     gPriv->distIOTblCnt    = NULL;
  131.  
  132.     return kQ3Success;
  133. }
  134.  
  135. static TQ3Status iDPG_Copy(
  136.     TQ3GroupObject                        fromGroup,
  137.     TQ3DistanceProxyDisplayGroupPrivate    *fromPriv,
  138.     TQ3GroupObject                        toGroup,
  139.     TQ3DistanceProxyDisplayGroupPrivate    *toPriv)
  140. {
  141.     register long i;
  142.     
  143.     toPriv->refPt            = fromPriv->refPt;
  144.     toPriv->flag            = fromPriv->flag;
  145.     toPriv->position         = NULL;
  146.     
  147.     toPriv->distTbl            = NULL;
  148.     toPriv->distTblCnt        = 0;
  149.     
  150.     toPriv->distIOTblCnt     = 0;
  151.     toPriv->distIOTbl         = dpgAlloc(sizeof(TQ3DistanceIOData)*fromPriv->distTblCnt);
  152.     if (!toPriv->distIOTbl) {
  153.         return kQ3Failure;
  154.     }
  155.     
  156.     toPriv->distIOTblCnt     = fromPriv->distTblCnt;
  157.     
  158.     for (i=0;i < fromPriv->distTblCnt;i++) {
  159.         TQ3GroupPosition position;
  160.         register long index;
  161.         
  162.         for (
  163.             Q3Group_GetFirstPosition(fromGroup, &position), index = 0; 
  164.             position != NULL; 
  165.             index++)
  166.         {
  167.             if (position == fromPriv->distTbl[i].position)
  168.             {
  169.                 toPriv->distIOTbl[i].distance = fromPriv->distTbl[i].distance;
  170.                 toPriv->distIOTbl[i].index    = index;
  171.                 break;
  172.             }
  173.             Q3Group_GetNextPosition(fromGroup, &position);
  174.         }
  175.     }
  176.     
  177.     return exDistanceProxyGroup_ProcessIO(toGroup, toPriv);
  178.     
  179. }
  180.  
  181. static long exDistanceProxyGroup_CompareDistance(
  182.     float            *key,
  183.     TQ3DistanceData    *data)
  184. {
  185.     float val = *key - data->distance;
  186.     
  187.     if (fabs(val) < ((float)1.19209290e-07)) 
  188.         return 0;
  189.     
  190.     if (val > 0.0)  
  191.         return  1;
  192.     return -1;
  193. }
  194.  
  195. /*===========================================================================*\
  196.  *
  197.  *    Routine:    exDistanceProxyGroup_Register()
  198.  *
  199.  *    Comments:    Registers the class.
  200.  *
  201. \*===========================================================================*/
  202. TQ3Status exDistanceProxyGroup_Register(
  203.     void)
  204. {
  205.     TQ3ObjectType objectType = kQ3DisplayGroupTypeDistanceProxy;
  206.     
  207.     EgDistanceProxyDisplayGroupClass =
  208.         Q3XObjectHierarchy_RegisterClass(
  209.             kQ3GroupTypeDisplay,
  210.             &objectType, 
  211.             "Apple Computer Inc.:Display Group:DistanceProxyDisplayGroup",
  212.             exDistanceProxyGroup_MetaHandler,
  213.             NULL,
  214.             0,
  215.             sizeof(TQ3DistanceProxyDisplayGroupPrivate));
  216.     
  217.     if (EgDistanceProxyDisplayGroupClass == NULL)
  218.         return kQ3Failure;
  219.     
  220.     return kQ3Success;
  221.  
  222. }
  223.  
  224. /*===========================================================================*\
  225.  *
  226.  *    Routine:    exDistanceProxyGroup_New()
  227.  *
  228.  *    Comments:    Constructor
  229.  *
  230. \*===========================================================================*/
  231.  
  232. TQ3GroupObject exDistanceProxyGroup_New(
  233.     TQ3Point3D         *refPt,
  234.     unsigned long     flag)
  235. {
  236.     TQ3DPGData data;
  237.     
  238.     data.refPt = *refPt;
  239.     data.flag  = flag;
  240.     
  241.     return
  242.         Q3XObjectHierarchy_NewObject(
  243.             EgDistanceProxyDisplayGroupClass,
  244.             (void *) &data);
  245. }
  246.  
  247. /*===========================================================================*\
  248.  *
  249.  *    Routine:    exDistanceProxyGroup_SetDistance()
  250.  *
  251.  *    Comments:    
  252.  *
  253. \*===========================================================================*/
  254.  
  255.  
  256. static TQ3Status exDistanceProxyGroup_SetDistance(
  257.     TQ3GroupObject                            group,
  258.     TQ3DistanceProxyDisplayGroupPrivate        *gPriv,
  259.     TQ3GroupPosition                        position,
  260.     float                                    distance)
  261. {
  262.     unsigned long        index;
  263.     TQ3DistanceData     data;
  264.     
  265.     data.position = position;
  266.     data.distance = distance;
  267.     
  268.     /* set private position data */
  269.     {
  270.         TQ3DPGPositionPrivate *pPriv;
  271.         pPriv = DPG_POSITION_GETPRIVATE(group, position);
  272.         pPriv->flag     = kQ3True;
  273.         pPriv->distance = distance;
  274.     }
  275.     
  276.     /* insertion sort */
  277.     
  278.     if (dpgSortedArray_Search(
  279.             (void *)&distance,
  280.             gPriv->distTbl,
  281.             gPriv->distTblCnt,
  282.             sizeof(TQ3DistanceData),
  283.             (dpgCompareFunction) exDistanceProxyGroup_CompareDistance,
  284.             &index) == kQ3True)
  285.     {
  286.         /* duplicate distance, replace with new one */
  287.         TQ3Object             object;
  288.         TQ3GroupPosition     oldPosition;
  289.         
  290.         oldPosition = gPriv->distTbl[index].position;
  291.         
  292.         /* call DefaultRemovePosition */
  293.         {
  294.             TQ3XGroupRemovePositionMethod     method;
  295.             TQ3XObjectClass                    objectClass;
  296.         
  297.             objectClass = Q3XObjectHierarchy_FindClassByType(kQ3GroupTypeDisplay);
  298.         
  299.             method = (TQ3XGroupRemovePositionMethod) Q3XObjectClass_GetMethod(
  300.                                                         objectClass, 
  301.                                                         kQ3XMethodType_GroupRemovePosition);
  302.  
  303.             object = (*method)(group, oldPosition);
  304.         }
  305.         
  306.         if(object)
  307.             Q3Object_Dispose(object);
  308.         
  309.         gPriv->distTbl[index] = data;
  310.  
  311.         
  312.         return kQ3Success;
  313.     }
  314.     else {
  315.         /* insert new data */
  316.         
  317.         gPriv->distTbl = dpgRealloc(
  318.                             gPriv->distTbl, 
  319.                             sizeof(TQ3DistanceData) * (gPriv->distTblCnt+1));
  320.  
  321.         if (gPriv->distTbl == NULL)
  322.         {
  323.             return kQ3Failure;
  324.         }
  325.  
  326.         dpgSortedArray_InsertElement(
  327.             gPriv->distTbl, 
  328.             gPriv->distTblCnt, 
  329.             sizeof(TQ3DistanceData),
  330.             &data,
  331.             index);
  332.             
  333.         gPriv->distTblCnt++;
  334.     }
  335.  
  336.     return kQ3Success;
  337. }
  338.  
  339. /*===========================================================================*\
  340.  *
  341.  *    Routine:    exDistanceProxyGroup_AcceptObject()
  342.  *
  343.  *    Comments:    
  344.  *
  345. \*===========================================================================*/
  346. static TQ3Boolean exDistanceProxyGroup_AcceptObject(
  347.     TQ3GroupObject        group,
  348.     TQ3Object            object)
  349. {    
  350.     group; /* Unused */
  351.     return Q3Object_IsDrawable(object);
  352. }
  353.  
  354.  
  355. /*===========================================================================*\
  356.  *
  357.  *    Routine:    exDistanceProxyGroup_AddObjectDistance()
  358.  *
  359.  *    Comments:    
  360.  *
  361. \*===========================================================================*/
  362. TQ3GroupPosition exDistanceProxyGroup_AddObjectDistance(
  363.     TQ3GroupObject        group,
  364.     TQ3Object            object,
  365.     float                distance)
  366. {
  367.     TQ3GroupPosition                     position;
  368.     TQ3DistanceProxyDisplayGroupPrivate    *gPriv;
  369.  
  370.     gPriv = DPG_GETPRIVATE(group);
  371.  
  372.     /*position = EiGroup_DefaultAddObject(group, object);*/
  373.     {
  374.         TQ3XGroupAddObjectMethod     method;
  375.         TQ3XObjectClass                objectClass;
  376.         
  377.         objectClass = Q3XObjectHierarchy_FindClassByType(kQ3GroupTypeDisplay);
  378.         method = (TQ3XGroupAddObjectMethod) Q3XObjectClass_GetMethod(
  379.                                                 objectClass, 
  380.                                                 kQ3XMethodType_GroupAddObject);
  381.  
  382.         position = (*method)(group, object);
  383.     }
  384.     
  385.  
  386.     exDistanceProxyGroup_SetDistance(group, gPriv, position, distance);
  387.     
  388.     return position;
  389. }
  390.  
  391. /*===========================================================================*\
  392.  *
  393.  *    Routine:    exDistanceProxyGroup_SetFlag()
  394.  *
  395.  *    Comments:    
  396.  *
  397. \*===========================================================================*/
  398. TQ3Status exDistanceProxyGroup_SetFlag(
  399.     TQ3GroupObject        group,
  400.     TQ3DPGFlag             flag)
  401. {
  402.     TQ3DistanceProxyDisplayGroupPrivate    *gPriv;
  403.  
  404.     gPriv = DPG_GETPRIVATE(group);
  405.  
  406.     gPriv->flag = flag;
  407.     
  408.     return kQ3Success;
  409. }
  410.  
  411. /*===========================================================================*\
  412.  *
  413.  *    Routine:    exDistanceProxyGroup_GetFlag()
  414.  *
  415.  *    Comments:    
  416.  *
  417. \*===========================================================================*/
  418. TQ3Status exDistanceProxyGroup_GetFlag(
  419.     TQ3GroupObject        group,
  420.     TQ3DPGFlag             *flag)
  421. {
  422.     TQ3DistanceProxyDisplayGroupPrivate    *gPriv;
  423.  
  424.     gPriv = DPG_GETPRIVATE(group);
  425.  
  426.     *flag = gPriv->flag;
  427.     
  428.     return kQ3Success;
  429. }
  430.  
  431. /*===========================================================================*\
  432.  *
  433.  *    Routine:    exDistanceProxyGroup_SetReferencePoint()
  434.  *
  435.  *    Comments:    
  436.  *
  437. \*===========================================================================*/
  438. TQ3Status exDistanceProxyGroup_SetReferencePoint(
  439.     TQ3GroupObject        group,
  440.     TQ3Point3D             *refPt)
  441. {
  442.     TQ3DistanceProxyDisplayGroupPrivate    *gPriv;
  443.  
  444.     gPriv = DPG_GETPRIVATE(group);
  445.  
  446.     gPriv->refPt = *refPt;;
  447.     
  448.     return kQ3Success;
  449. }
  450.  
  451. /*===========================================================================*\
  452.  *
  453.  *    Routine:    exDistanceProxyGroup_GetReferencePoint()
  454.  *
  455.  *    Comments:    
  456.  *
  457. \*===========================================================================*/
  458. TQ3Status exDistanceProxyGroup_GetReferencePoint(
  459.     TQ3GroupObject        group,
  460.     TQ3Point3D             *refPt)
  461. {
  462.     TQ3DistanceProxyDisplayGroupPrivate    *gPriv;
  463.  
  464.     gPriv = DPG_GETPRIVATE(group);
  465.  
  466.     *refPt = gPriv->refPt;
  467.     
  468.     return kQ3Success;
  469. }
  470.  
  471. /*===========================================================================*\
  472.  *
  473.  *    Routine:    exDistanceProxyGroup_SetDistanceAtPosition()
  474.  *
  475.  *    Comments:    
  476.  *
  477. \*===========================================================================*/
  478. TQ3Boolean exDistanceProxyGroup_SetDistanceAtPosition(
  479.     TQ3GroupObject        group,
  480.     TQ3GroupPosition    position,
  481.     float                distance)
  482. {
  483.     TQ3DistanceProxyDisplayGroupPrivate    *gPriv;
  484.     unsigned long                         index;
  485.     TQ3DPGPositionPrivate                 *pPriv;
  486.  
  487.     gPriv = DPG_GETPRIVATE(group);
  488.  
  489.     
  490.     pPriv = DPG_POSITION_GETPRIVATE(group, position);
  491.     if (pPriv->flag) 
  492.     {    
  493.     
  494.         pPriv->distance = distance;
  495.         
  496.         /* now fix up the distance table */
  497.         if (dpgSortedArray_Search(
  498.                 (void *)&pPriv->distance,
  499.                 gPriv->distTbl,
  500.                 gPriv->distTblCnt,
  501.                 sizeof(TQ3DistanceData),
  502.                 (dpgCompareFunction) exDistanceProxyGroup_CompareDistance,
  503.                 &index) == kQ3True)
  504.         {
  505.             /* found it, now get rid of it */
  506.             dpgSortedArray_DeleteElement(
  507.                 gPriv->distTbl,
  508.                 gPriv->distTblCnt,
  509.                 sizeof(TQ3DistanceData),
  510.                 NULL,
  511.                 index);
  512.         
  513.             gPriv->distTblCnt--;
  514.             
  515.             if (dpgSortedArray_Search(
  516.                     (void *)&distance,
  517.                     gPriv->distTbl,
  518.                     gPriv->distTblCnt,
  519.                     sizeof(TQ3DistanceData),
  520.                     (dpgCompareFunction) exDistanceProxyGroup_CompareDistance,
  521.                     &index) == kQ3False)
  522.             {
  523.                 TQ3DistanceData     data;
  524.             
  525.                 data.position = position;
  526.                 data.distance = distance;
  527.  
  528.                 dpgSortedArray_InsertElement(
  529.                     gPriv->distTbl, 
  530.                     gPriv->distTblCnt, 
  531.                     sizeof(TQ3DistanceData),
  532.                     &data,
  533.                     index);
  534.             }    
  535.                 
  536.             gPriv->distTblCnt++;
  537.         }
  538.         
  539.  
  540.         return kQ3True;
  541.     }
  542.     return kQ3False;
  543. }
  544.  
  545. /*===========================================================================*\
  546.  *
  547.  *    Routine:    exDistanceProxyGroup_GetDistanceAtPosition()
  548.  *
  549.  *    Comments:    
  550.  *
  551. \*===========================================================================*/
  552. TQ3Boolean exDistanceProxyGroup_GetDistanceAtPosition(
  553.     TQ3GroupObject        group,
  554.     TQ3GroupPosition    position,
  555.     float                *distance)
  556. {
  557.     TQ3DistanceProxyDisplayGroupPrivate    *gPriv;
  558.     TQ3DPGPositionPrivate                 *pPriv;
  559.  
  560.     gPriv = DPG_GETPRIVATE(group);
  561.     pPriv = DPG_POSITION_GETPRIVATE(group, position);
  562.  
  563.  
  564.     *distance = 0.0;
  565.     
  566.     if (pPriv->flag)
  567.     {
  568.         *distance = pPriv->distance;
  569.         return kQ3True;
  570.     }
  571.     
  572.     return kQ3False;
  573. }
  574.  
  575.  
  576. /*===========================================================================*\
  577.  *
  578.  *    Routine:    exDistanceProxyGroup_RemovePosition()
  579.  *
  580.  *    Comments:    
  581.  *
  582. \*===========================================================================*/
  583. static TQ3Object exDistanceProxyGroup_RemovePosition(
  584.     TQ3GroupObject        group,
  585.     TQ3GroupPosition    position)
  586. {
  587.     unsigned long     index;
  588.  
  589.     TQ3DistanceProxyDisplayGroupPrivate    *gPriv;
  590.     TQ3DPGPositionPrivate                 *pPriv;
  591.  
  592.     gPriv = DPG_GETPRIVATE(group);
  593.     pPriv = DPG_POSITION_GETPRIVATE(group, position);
  594.  
  595.     if (pPriv->flag)
  596.     {
  597.         /* now remove distance entry */    
  598.         
  599.         if (dpgSortedArray_Search(
  600.             (void *)&pPriv->distance,
  601.             gPriv->distTbl,
  602.             gPriv->distTblCnt,
  603.             sizeof(TQ3DistanceData),
  604.             (dpgCompareFunction) exDistanceProxyGroup_CompareDistance,
  605.             &index) == kQ3True)
  606.         {
  607.             dpgSortedArray_DeleteElement(
  608.                 gPriv->distTbl,
  609.                 gPriv->distTblCnt,
  610.                 sizeof(TQ3DistanceData),
  611.                 NULL,
  612.                 index);
  613.         
  614.             gPriv->distTblCnt--;
  615.         
  616.             dpgSortedArray_Resize(
  617.                     (void **) &gPriv->distTbl,
  618.                     gPriv->distTblCnt,
  619.                     sizeof(TQ3DistanceData));
  620.         }                
  621.                 
  622.     }
  623.  
  624.     /* call DefaultRemovePosition */
  625.     {
  626.         TQ3XGroupRemovePositionMethod method;
  627.         TQ3XObjectClass                objectClass;
  628.         
  629.         objectClass = Q3XObjectHierarchy_FindClassByType(kQ3GroupTypeDisplay);
  630.         
  631.         method = (TQ3XGroupRemovePositionMethod) Q3XObjectClass_GetMethod(
  632.                                                     objectClass, 
  633.                                                     kQ3XMethodType_GroupRemovePosition);
  634.  
  635.         return (*method)(group, position);
  636.     }
  637. }
  638.  
  639. /*===========================================================================*\
  640.  *
  641.  *    Routine:    exDistanceProxyGroup_EndRead()
  642.  *
  643.  *    Comments:    
  644.  *
  645. \*===========================================================================*/
  646. static TQ3Status exDistanceProxyGroup_EndRead(
  647.     TQ3GroupObject    group)
  648. {
  649.     TQ3DistanceProxyDisplayGroupPrivate    *gPriv;
  650.     
  651.     gPriv = DPG_GETPRIVATE(group);
  652.         
  653.     exDistanceProxyGroup_ProcessIO(group, gPriv);
  654.  
  655.     return kQ3Success;
  656. }
  657.  
  658. /*===========================================================================*\
  659.  *
  660.  *    Routine:    exDistanceProxyGroup_StartState()
  661.  *
  662.  *    Comments:    
  663.  *
  664. \*===========================================================================*/
  665. static TQ3Status exDistanceProxyGroup_StartState(
  666.     TQ3GroupObject    group,
  667.     TQ3ViewObject    view)
  668. {
  669.     TQ3DisplayGroupState state;
  670.  
  671.     Q3DisplayGroup_GetState(group, &state);
  672.     
  673.     if ((state & kQ3DisplayGroupStateMaskIsInline) == 0)
  674.     {
  675.         if (Q3Push_Submit(view) == kQ3Failure)
  676.             return kQ3Failure;
  677.     }
  678.     return kQ3Success;
  679. }
  680.  
  681. /*===========================================================================*\
  682.  *
  683.  *    Routine:    exDistanceProxyGroup_EndState()
  684.  *
  685.  *    Comments:    
  686.  *
  687. \*===========================================================================*/
  688. static TQ3Status exDistanceProxyGroup_EndState(
  689.     TQ3GroupObject    group,
  690.     TQ3ViewObject    view)
  691. {
  692.     TQ3DisplayGroupState state;
  693.  
  694.     Q3DisplayGroup_GetState(group, &state);
  695.  
  696.     if ((state & kQ3DisplayGroupStateMaskIsInline) == 0)
  697.     {
  698.         if (Q3Pop_Submit(view) == kQ3Failure)
  699.             return kQ3Failure;
  700.     }
  701.     return kQ3Success;
  702. }
  703.  
  704. /*===========================================================================*\
  705.  *
  706.  *    Routine:    exDistanceProxyGroup_StartIterate()
  707.  *
  708.  *    Comments:    
  709.  *
  710. \*===========================================================================*/
  711. static TQ3Status exDistanceProxyGroup_StartIterate(
  712.     TQ3GroupObject            group,
  713.     TQ3GroupPosition        *position,
  714.     TQ3Object                *object,
  715.     TQ3ViewObject            view)
  716. {
  717.     TQ3DistanceProxyDisplayGroupPrivate    *gPriv;
  718.     TQ3Status status;
  719.     
  720.     gPriv = DPG_GETPRIVATE(group);
  721.  
  722.     /* calculate current distance */
  723.     if (exDistanceProxyGroup_CalculateDistance(view, gPriv) == kQ3Failure)
  724.         return kQ3Failure;
  725.     
  726.     *position = NULL;
  727.     *object      = NULL;
  728.     
  729.     status = Q3Group_GetFirstPosition(group, position);
  730.  
  731.     /* find first visible object */
  732.     
  733.     
  734.     while ((status != kQ3Failure) &&
  735.             *position &&
  736.             exDistanceProxyGroup_Find(group, *position) == kQ3False) 
  737.     {
  738.         status = Q3Group_GetNextPosition(group, position);
  739.     }
  740.         
  741.     if (status == kQ3Failure) {
  742.         *position = NULL;
  743.         return kQ3Failure;
  744.     }
  745.  
  746.     /* nothing to draw */
  747.     if (*position == NULL)
  748.         return kQ3Success;
  749.     
  750.     if (Q3Group_GetPositionObject(group, *position, object) == kQ3Failure)
  751.         return kQ3Failure;
  752.     
  753.     if (exDistanceProxyGroup_StartState(group, view) == kQ3Failure)
  754.     {
  755.         Q3Object_Dispose(*object);
  756.         *object = NULL;
  757.         return kQ3Failure;
  758.     }
  759.  
  760.     return kQ3Success;
  761. }
  762.  
  763. /*===========================================================================*\
  764.  *
  765.  *    Routine:    exDistanceProxyGroup_EndIterate()
  766.  *
  767.  *    Comments:    
  768.  *
  769. \*===========================================================================*/
  770. static TQ3Status exDistanceProxyGroup_EndIterate(
  771.     TQ3GroupObject            group,
  772.     TQ3GroupPosition        *position,
  773.     TQ3Object                *object,
  774.     TQ3ViewObject            view)
  775. {
  776.     TQ3Status status;
  777.  
  778.     if (*object != NULL)
  779.     {
  780.         Q3Object_Dispose(*object);
  781.         *object = NULL;
  782.  
  783.         status = Q3Group_GetNextPosition(group, position);
  784.  
  785.         while (    (status == kQ3Success) && 
  786.                 *position && 
  787.                 (exDistanceProxyGroup_Find(group, *position) == kQ3False)) 
  788.         {
  789.             status = Q3Group_GetNextPosition(group, position);
  790.         }
  791.         
  792.         if (*position == NULL || status == kQ3Failure)
  793.         {
  794.             return exDistanceProxyGroup_EndState(group, view);
  795.         }
  796.     
  797.         return Q3Group_GetPositionObject(group, *position, object);
  798.     }
  799.     
  800.     *position = NULL;
  801.     return exDistanceProxyGroup_EndState(group, view);
  802. }
  803.  
  804.  
  805. /*===========================================================================*\
  806.  *
  807.  *    Routine:    exDistanceProxyGroup_CalculateDistance()
  808.  *
  809.  *    Comments:    
  810.  *
  811. \*===========================================================================*/
  812. static TQ3Status exDistanceProxyGroup_CalculateDistance(
  813.     TQ3ViewObject                        view,
  814.     TQ3DistanceProxyDisplayGroupPrivate    *gPriv)
  815. {
  816.     TQ3CameraObject     camera;
  817.     TQ3CameraPlacement    placement;
  818.     TQ3Matrix4x4        matrix;
  819.     TQ3Point3D            transPt;
  820.     
  821.     Q3View_GetCamera (view, &camera);
  822.     if (!camera)
  823.         return kQ3Failure;
  824.         
  825.     Q3Camera_GetPlacement(camera, &placement);
  826.     Q3Object_Dispose(camera);
  827.     
  828.     if (Q3View_GetLocalToWorldMatrixState(view, &matrix) == kQ3Failure)
  829.         return kQ3Failure;
  830.         
  831.     Q3Point3D_Transform(&gPriv->refPt, &matrix, &transPt);
  832.     
  833.     /* found the distance */
  834.     gPriv->d = Q3Point3D_Distance(&placement.cameraLocation, &transPt);
  835.  
  836.     /* now find the position to draw */    
  837.     {    
  838.         register long highElem    = gPriv->distTblCnt - 1;
  839.         register long midElem    = highElem / 2;
  840.         register long lowElem    = 0;
  841.         register long direction    = 1;
  842.     
  843.         register TQ3DistanceData    *distTbl;
  844.         
  845.         distTbl = gPriv->distTbl;
  846.  
  847.         /* d >= MAX distance so use last object */
  848.         if (gPriv->d >= distTbl[highElem].distance && gPriv->flag != kQ3DPG_ClipWhenFar)
  849.         {
  850.             gPriv->position = distTbl[highElem].position;
  851.             return kQ3Success;
  852.  
  853.         }
  854.         /* d < MIN distance so use first object */
  855.         if (gPriv->d < distTbl[0].distance && gPriv->flag != kQ3DPG_HideWhenNear)
  856.         {
  857.             gPriv->position = distTbl[0].position;
  858.             return kQ3Success;
  859.         }
  860.         
  861.         /* d is in range, find the right object */
  862.         while (highElem >= lowElem)
  863.         {
  864.             direction = gPriv->d - distTbl[midElem].distance;
  865.             
  866.             if ((direction == 0) ||
  867.                 (gPriv->d >= distTbl[midElem-1].distance && 
  868.                  gPriv->d < distTbl[midElem].distance))
  869.             {
  870.                 gPriv->position = distTbl[midElem].position;
  871.                 return kQ3Success;
  872.             }    
  873.             
  874.             if (direction > 0)
  875.                 lowElem  = midElem + 1;
  876.             else
  877.                 highElem = midElem - 1;
  878.                 
  879.             midElem = (highElem + lowElem) >> 1;
  880.         }
  881.     }
  882.     return kQ3Failure;
  883. }
  884.  
  885. /*===========================================================================*\
  886.  *
  887.  *    Routine:    exDistanceProxyGroup_Find()
  888.  *
  889.  *    Comments:    
  890.  *
  891. \*===========================================================================*/
  892. static TQ3Boolean exDistanceProxyGroup_Find(
  893.     TQ3GroupObject            group,
  894.     TQ3GroupPosition        position)
  895. {
  896.     TQ3DistanceProxyDisplayGroupPrivate    *gPriv;
  897.     TQ3DPGPositionPrivate                 *pPriv;
  898.  
  899.     gPriv = DPG_GETPRIVATE(group);
  900.     pPriv = DPG_POSITION_GETPRIVATE(group, position);
  901.  
  902.     if (pPriv->flag == kQ3False)
  903.     {
  904.         /* it's a object that doesn't have a distance 
  905.         ** assume it want to be drawn 
  906.         */
  907.         return kQ3True;
  908.     }
  909.     
  910.     if (position == gPriv->position)
  911.         return kQ3True;
  912.     else
  913.         return kQ3False;
  914. }
  915.  
  916. /*===========================================================================*\
  917.  *
  918.  *    Routine:    exDistanceProxyGroup_ProcessIO()
  919.  *
  920.  *    Comments:    
  921.  *
  922. \*===========================================================================*/
  923.  
  924. static TQ3Status exDistanceProxyGroup_ProcessIO(
  925.     TQ3GroupObject                        group,
  926.     TQ3DistanceProxyDisplayGroupPrivate    *gPriv)
  927. {
  928.     if (gPriv->distIOTbl) 
  929.     {
  930.         TQ3GroupPosition position;
  931.         unsigned long index = 0;
  932.         unsigned long cnt   = 0;
  933.         
  934.         for (Q3Group_GetFirstPosition(group, &position); position != NULL;cnt++)
  935.         {
  936.             if (gPriv->distIOTbl[index].index == cnt) 
  937.             {
  938.                 if (exDistanceProxyGroup_SetDistance(
  939.                     group, 
  940.                     gPriv, 
  941.                     position, 
  942.                     gPriv->distIOTbl[index].distance) == kQ3Failure)
  943.                 {
  944.                     gPriv->distTblCnt = 0;
  945.                     dpgFree(gPriv->distTbl);
  946.                     gPriv->distTbl = NULL;
  947.                     return kQ3Failure;
  948.                 }
  949.                 index++;
  950.             }
  951.             Q3Group_GetNextPosition(group, &position);
  952.         } 
  953.     
  954.         dpgFree(gPriv->distIOTbl);
  955.         
  956.         gPriv->distIOTbl     = NULL;
  957.         gPriv->distIOTblCnt = 0;
  958.     }
  959.     return kQ3Success;
  960. }
  961.  
  962. /*===========================================================================*\
  963.  *
  964.  *    Routine:    exDistanceProxyGroup_PositionNew()
  965.  *
  966.  *    Comments:    
  967.  *
  968. \*===========================================================================*/
  969.  
  970. static TQ3Status exDistanceProxyGroup_PositionNew(
  971.     TQ3DPGPositionPrivate    *gPos,
  972.     TQ3Object                object,
  973.     const TQ3Boolean        *initData)
  974. {
  975.     object; /* XXX Unused */
  976.     
  977.     if (initData == NULL)
  978.         gPos->flag = kQ3False;
  979.     else
  980.         gPos->flag = *initData;
  981.     
  982.     gPos->distance = 0.0;
  983.     
  984.     return kQ3Success;
  985. }
  986.  
  987. /*===========================================================================*\
  988.  *
  989.  *    Routine:    exDistanceProxyGroup_PositionCopy()
  990.  *
  991.  *    Comments:    
  992.  *
  993. \*===========================================================================*/
  994. static TQ3Status exDistanceProxyGroup_PositionCopy(
  995.     TQ3DPGPositionPrivate    *srcGPos,
  996.     TQ3DPGPositionPrivate    *dstGPos)
  997. {
  998.     *dstGPos = *srcGPos;
  999.     return kQ3Success;
  1000. }
  1001.  
  1002. /*===========================================================================*\
  1003.  *
  1004.  *    Routine:    exDistanceProxyGroup_MetaHandler()
  1005.  *
  1006.  *    Comments:    
  1007.  *
  1008. \*===========================================================================*/
  1009. static TQ3XFunctionPointer exDistanceProxyGroup_MetaHandler(
  1010.     TQ3XMethodType        methodType)
  1011. {
  1012.     switch (methodType) {
  1013.         case kQ3XMethodTypeObjectNew:
  1014.             return (TQ3XFunctionPointer) iDPG_New;
  1015.         case kQ3XMethodTypeObjectDuplicate:
  1016.             return (TQ3XFunctionPointer) iDPG_Copy;
  1017.         case kQ3XMethodTypeObjectRead:
  1018.             return (TQ3XFunctionPointer) exDistanceProxyGroup_Read;
  1019.         case kQ3XMethodTypeObjectTraverse:
  1020.             return (TQ3XFunctionPointer) exDistanceProxyGroup_Traverse;
  1021.         case kQ3XMethodTypeObjectWrite:                
  1022.             return (TQ3XFunctionPointer) exDistanceProxyGroup_Write;
  1023.     
  1024.         case kQ3XMethodType_GroupAcceptObject:
  1025.             return (TQ3XFunctionPointer) exDistanceProxyGroup_AcceptObject;
  1026.         case kQ3XMethodType_GroupRemovePosition:
  1027.             return (TQ3XFunctionPointer) exDistanceProxyGroup_RemovePosition;
  1028.         
  1029.         case kQ3XMethodType_GroupStartIterate:
  1030.             return (TQ3XFunctionPointer) exDistanceProxyGroup_StartIterate;
  1031.         case kQ3XMethodType_GroupEndIterate:
  1032.             return (TQ3XFunctionPointer) exDistanceProxyGroup_EndIterate;
  1033.     
  1034.         case kQ3XMethodType_GroupEndRead:
  1035.             return (TQ3XFunctionPointer) exDistanceProxyGroup_EndRead;
  1036.     
  1037.         case kQ3XMethodType_GroupPositionSize:
  1038.             return (TQ3XFunctionPointer)     sizeof(TQ3DPGPositionPrivate);
  1039.         case kQ3XMethodType_GroupPositionNew:
  1040.             return (TQ3XFunctionPointer)     exDistanceProxyGroup_PositionNew;
  1041.         case kQ3XMethodType_GroupPositionCopy:
  1042.             return (TQ3XFunctionPointer)     exDistanceProxyGroup_PositionCopy;
  1043.         
  1044.         case kQ3XMethodTypeObjectIsDrawable:
  1045.             return (TQ3XFunctionPointer) kQ3True;
  1046.         
  1047.         default:
  1048.             return (TQ3XFunctionPointer) NULL;
  1049.     }
  1050. }
  1051.  
  1052.  
  1053. #if defined(OS_WIN32) && OS_WIN32
  1054.  
  1055.     /*===========================================================================*\
  1056.      *
  1057.      *    Routine:    DllMain()
  1058.      *
  1059.      *    Comments:    The Win32 extension entry point
  1060.      *
  1061.     \*===========================================================================*/
  1062.     BOOL WINAPI _CRT_INIT(
  1063.         HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
  1064.  
  1065.     BOOL WINAPI DllMain(
  1066.         HINSTANCE    hinstDLL,
  1067.         DWORD        fdwReason,
  1068.         LPVOID        lpvReserved)
  1069.     {
  1070.         TQ3XSharedLibraryInfo    sharedLibraryInfo;
  1071.         
  1072.         if ((fdwReason == DLL_PROCESS_ATTACH) || (fdwReason == DLL_THREAD_ATTACH))
  1073.             if (!_CRT_INIT(hinstDLL, fdwReason, lpvReserved))
  1074.                 return (FALSE);
  1075.         if (fdwReason == DLL_PROCESS_ATTACH)
  1076.         {
  1077.             sharedLibraryInfo.registerFunction = exDistanceProxyGroup_Register;
  1078.             sharedLibraryInfo.sharedLibrary = (unsigned long)hinstDLL;
  1079.             if (Q3XSharedLibrary_Register(&sharedLibraryInfo) == kQ3Success) 
  1080.                 return TRUE;
  1081.             else
  1082.                 return FALSE;
  1083.         }
  1084.         else if (fdwReason == DLL_PROCESS_DETACH || fdwReason == DLL_THREAD_DETACH)
  1085.             if (!_CRT_INIT(hinstDLL, fdwReason, lpvReserved))
  1086.                 return (FALSE);
  1087.         if (fdwReason == DLL_PROCESS_DETACH)
  1088.         {
  1089.             Q3XSharedLibrary_Unregister( (unsigned long)hinstDLL);
  1090.             return TRUE;
  1091.         }
  1092.  
  1093.         return (TRUE);
  1094.     }
  1095.  
  1096. #endif /* OS_WIN32 */
  1097.  
  1098. #if defined(OS_MACINTOSH) && OS_MACINTOSH
  1099.  
  1100. OSErr  DPGInitialize(const CFragInitBlock *    initBlock)
  1101. {
  1102.     TQ3XSharedLibraryInfo    sharedLibraryInfo;
  1103.         
  1104.     sharedLibraryInfo.registerFunction = exDistanceProxyGroup_Register;
  1105.     sharedLibraryInfo.sharedLibrary = (unsigned long)initBlock->connectionID;
  1106.     Q3XSharedLibrary_Register(&sharedLibraryInfo);
  1107.     
  1108.     EgSharedLibrary = (unsigned long)initBlock->connectionID;
  1109.     return noErr;
  1110. }
  1111.  
  1112.  
  1113. TQ3Status DPGExit(void)
  1114. {
  1115.     if( EgSharedLibrary != NULL ) {
  1116.         Q3XSharedLibrary_Unregister(EgSharedLibrary);
  1117.         EgSharedLibrary = NULL;
  1118.     }
  1119.         
  1120.     return kQ3Success;
  1121. }
  1122.  
  1123. #endif
  1124.  
  1125. #if 0
  1126.  
  1127. /* outdated */
  1128.  
  1129. long DPG_Init(
  1130.     void)
  1131. {    
  1132.     if (!Q3IsInitialized()) {
  1133.     
  1134.         if (Q3Initialize() == kQ3Failure)
  1135.         {
  1136.             return 1;
  1137.         }
  1138.     }
  1139.     
  1140.     if (exDistanceProxyGroup_Register() == kQ3Failure)
  1141.     {
  1142.         return 1;
  1143.     }
  1144.  
  1145.     return 0;
  1146. }
  1147.  
  1148. long DPG_Exit(
  1149.     void)
  1150. {
  1151.     
  1152.     return 0;
  1153. }
  1154.  
  1155. #endif